package com.zmj.sy.mom.srv.aps.service;

import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.zmj.sy.mom.srv.aps.bean.entity.resource.Group;
import com.zmj.sy.mom.srv.aps.bean.entity.resource.Phase;
import com.zmj.sy.mom.srv.aps.bean.entity.resource.PhaseGroup;
import com.zmj.sy.mom.srv.aps.bean.vo.base.BaseIdReqVo;
import com.zmj.sy.mom.srv.aps.bean.vo.base.BaseListResVo;
import com.zmj.sy.mom.srv.aps.bean.vo.base.BasePageResVo;
import com.zmj.sy.mom.srv.aps.bean.vo.base.BaseSelectItemResVo;
import com.zmj.sy.mom.srv.aps.bean.vo.phase.*;
import com.zmj.sy.mom.srv.aps.mapper.GroupMapper;
import com.zmj.sy.mom.srv.aps.mapper.PhaseGroupMapper;
import com.zmj.sy.mom.srv.aps.mapper.PhaseMapper;
import com.zmj.sy.mom.srv.aps.utils.MkBeanUtils;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@RequiredArgsConstructor
@Service
public class PhaseService {

    private final PhaseMapper phaseMapper;

    private final PhaseGroupMapper phaseGroupMapper;

    private final GroupMapper groupMapper;

    public BasePageResVo<PhaseListResVo> list(PhaseListReqVo reqVo) {

        if(StringUtils.hasText(reqVo.getMyCode())){

            reqVo.setMyCode(reqVo.getMyCode().replaceAll("\\d+",""));
        }

        Page<Phase> page = phaseMapper.lambdaQuery()
                .eq(Phase::getDeleted, 0)
                .like(StringUtils.hasText(reqVo.getName()), Phase::getName, reqVo.getName())
                .like(StringUtils.hasText(reqVo.getMyCode()), Phase::getMyCode, reqVo.getMyCode())
                .page(reqVo.toPage());

        if(CollUtil.isEmpty(page.getRecords())){
            return new BasePageResVo<>(page.getTotal(), CollUtil.newArrayList());
        }

        List<PhaseGroup> list = phaseGroupMapper.lambdaQuery().in(PhaseGroup::getPhaseCode, page.getRecords().stream().map(Phase::getMyCode).distinct().collect(Collectors.toList())).list();
        Map<String, List<PhaseGroup>> phaseGroupMap = list.stream().collect(Collectors.groupingBy(PhaseGroup::getPhaseCode));


        List<PhaseListResVo> collect = page.getRecords()
                .stream()
                .map(e -> {
                    PhaseListResVo r = new PhaseListResVo();
                    r.setId(e.getId());
                    r.setName(e.getName());
                    r.setMyCode(e.getMyCode());
                    List<PhaseGroup> phaseGroups = phaseGroupMap.get(e.getMyCode());
                    if(ObjectUtils.isNotEmpty(phaseGroups)){
                        r.setGroupCode(phaseGroups.stream().map(PhaseGroup::getGroupCode).collect(Collectors.joining(",")));
                        r.setGroupName(r.getGroupCode());
                        List<String> groupIds = phaseGroups.stream().map(PhaseGroup::getGroupCode).collect(Collectors.toList());
                        List<Group> list1 = groupMapper.lambdaQuery().in(Group::getMyCode, groupIds).list();
                        Map<String, Group> collect1 = list1.stream().collect(Collectors.toMap(Group::getMyCode, e2 -> e2));
                        r.setGroupId(phaseGroups.stream().filter(e1-> collect1.containsKey(e1.getGroupCode())).map(e1-> collect1.get(e1.getGroupCode()).getId().toString()).collect(Collectors.joining(",")));
                    }

                    return r;
                })
                .collect(Collectors.toList());

        return new BasePageResVo<>(page.getTotal(), collect);
    }

    @Transactional
    public void add(PhaseAddReqVo reqVo) {
        Phase phase = MkBeanUtils.copyProperties(reqVo, Phase.class);
        phaseMapper.insert(phase);

        String groupCode = reqVo.getGroupCode();
        if(!StringUtils.hasText(groupCode)){
            return ;
        }

        String[] split = reqVo.getGroupCode().split(",");
        if (CollUtil.isEmpty(Arrays.asList(split))) {
            return ;
        }

        List<PhaseGroup> collect = Arrays.stream(split)
                .map(e -> {
                    PhaseGroup phaseGroup = MkBeanUtils.copyProperties(reqVo, PhaseGroup.class);
                    phaseGroup.setPhaseCode(reqVo.getMyCode());
                    phaseGroup.setGroupCode(e);
                    return phaseGroup;
                })
                .collect(Collectors.toList());
        phaseGroupMapper.insertBatch(collect);
    }

    @Transactional
    public void edit(PhaseEditReqVo reqVo) {
        Phase phase = MkBeanUtils.copyProperties(reqVo, Phase.class);

        phaseMapper.updateById(phase);

        phaseGroupMapper.lambdaUpdate()
                .eq(PhaseGroup::getDeleted, 0)
                .eq(PhaseGroup::getPhaseCode, reqVo.getMyCode())
                .set(PhaseGroup::getDeleted, 1)
                .update();

        String groupCode = reqVo.getGroupCode();
        if(!StringUtils.hasText(groupCode)){
            return ;
        }

        String[] split = reqVo.getGroupCode().split(",");
        if (CollUtil.isEmpty(Arrays.asList(split))) {
            return ;
        }

        List<PhaseGroup> collect = Arrays.stream(split)
                .map(e -> {
                    PhaseGroup phaseGroup = MkBeanUtils.copyProperties(reqVo, PhaseGroup.class);
                    phaseGroup.setPhaseCode(reqVo.getMyCode());
                    phaseGroup.setGroupCode(e);
                    return phaseGroup;
                })
                .collect(Collectors.toList());
        phaseGroupMapper.insertBatch(collect);

    }

    @Transactional
    public void delete(BaseIdReqVo reqVo) {
        Phase phase = phaseMapper.lambdaQuery()
                .eq(Phase::getId, reqVo.getId())
                .eq(Phase::getDeleted, 0)
                .one();

        List<PhaseGroup> phaseGroupList = phaseGroupMapper.lambdaQuery()
                .eq(PhaseGroup::getDeleted, 0)
                .eq(PhaseGroup::getPhaseCode, phase.getMyCode())
                .list();
        if(ObjectUtils.isNotEmpty(phaseGroupList)){
            List<Integer> ids = phaseGroupList.stream().map(PhaseGroup::getId).collect(Collectors.toList());
            phaseGroupMapper.deleteBatchIds(ids);
        }
        phaseMapper.deleteById(reqVo.getId());
    }

    @Transactional
    public List<BaseSelectItemResVo> select(PhaseSelectReqVo reqVo) {
        List<Phase> list = phaseMapper.lambdaQuery()
                .like(StringUtils.hasText(reqVo.getText()), Phase::getName, reqVo.getText())
                .like(StringUtils.hasText(reqVo.getText()), Phase::getMyCode, reqVo.getText())
                .list();

        return list.stream()
                .map(e->{
                    BaseSelectItemResVo item = new BaseSelectItemResVo();
                    item.setText(e.getMyCode() + "-" +  e.getName());
                    item.setValue(e.getId());
                    return item;
                })
                .collect(Collectors.toList());
    }


    @Transactional
    public List<BaseSelectItemResVo> selectAll(PhaseSelectReqVo reqVo) {
        List<Phase> list = phaseMapper.lambdaQuery()
                .like(StringUtils.hasText(reqVo.getText()), Phase::getName, reqVo.getText())
                .like(StringUtils.hasText(reqVo.getText()), Phase::getMyCode, reqVo.getText())
                .list();

        return list.stream()
                .map(e->{
                    BaseSelectItemResVo item = new BaseSelectItemResVo();
                    item.setText(e.getMyCode() + "-" +  e.getName());
                    item.setValue(e.getId());
                    return item;
                })
                .collect(Collectors.toList());
    }

    public BaseListResVo<PhaseListResVo> listAll(PhaseListReqVo reqVo) {
        List<Phase> list = phaseMapper.lambdaQuery()
                .like(StringUtils.hasText(reqVo.getName()), Phase::getName, reqVo.getName())
                .like(StringUtils.hasText(reqVo.getMyCode()), Phase::getMyCode, reqVo.getMyCode())
                .orderByAsc(Phase::getMyCode)
                .list();

        List<PhaseListResVo> collect = list.stream()
                .map(e -> MkBeanUtils.copyProperties(e, PhaseListResVo.class))
                .collect(Collectors.toList());
        return BaseListResVo.of(collect, PhaseListResVo.class);
    }
}
